DodoRunner.Collision = function ($, _, app) {

    var fetchedCollision = false;
    var observable = {};
    var obstacles = [];
    var ground;
    var tracingObj;

    var registerObstacle = function (obstacle) {
        obstacles.push(obstacle);
    },
    removeObstacle = function (obstacle) {
        obstacles.splice(obstacles.indexOf(obstacle));
    },
    clear = function () {
        obstacles = [];
    },
    registerTracingObject = function (model) {
        tracingObj = model;
    },
    registerGround = function (obj) {
        ground = obj;
    },
    update = function () {
        var x = tracingObj.getX();
        var y = tracingObj.getY();
        var tileIndex = Math.round((x / app.GroundModel.TILE_SIZE));
        checkGround(tileIndex);
        checkObstacles(x, y);
        requestAnimationFrame(update);
    },
    checkGround = function (tileIndex) {
        if (!ground.isGroundSolid(tileIndex) && tracingObj.isRunning()) {
            collide(tracingObj, {}, "Pit Fall");
        }
    },
    checkObstacles = function (xPos, yPos) {
        for (var i = 0, max = obstacles.length; i < max; i++) {
            if (obstacles[i].TYPE == DodoRunner.Obstacle.TYPE_CIRCLE) {
                collideCircle(obstacles[i]);
            }
            else if(obstacles[i].TYPE == DodoRunner.Obstacle.TYPE_RECT)
            {
                collideRect(obstacles[i]);
            }
            else if(obstacles[i].TYPE == DodoRunner.Obstacle.TYPE_SPIKES)
            {
                collideRect(obstacles[i]);
            }
        }
    },
    collideRect = function (obj) {
        if (checkCollisionRect(obj.x, obj.y, obj.width, obj.height, tracingObj.getX(), tracingObj.getY(), tracingObj.getWidth(), tracingObj.getHeight())) {
            console.log(obj, tracingObj);
            collide(tracingObj, obj, "rect");
        }
    },
    collideCircle = function (obj) {
        if (checkCollisionCircle(tracingObj.getX(),tracingObj.getY(),tracingObj.getWidth(), tracingObj.getHeight(), obj.x, obj.y, obj.diameter)){
            collide(tracingObj, obj, "circle");
        }
    },

    checkCollisionRect = function (x1, y1, width1, height1, x2, y2, width2, height2) {

        y2 += 80;
        height2 -= 80;

        if(tracingObj.isSliding()){
            y2 += 20;
            height2 -= 20;
        };

        var right1 = x1 + width1, right2 = x2 + width2;
        var bottom1 = y1 + height1, bottom2 = y2 + height2;

        if (bottom1 < y2) return false;
        if (y1 > bottom2) return false;

        if (right1 < x2) return false;
        if (x1 > right2) return false;

        return true;
    },

    checkCollisionCircle = function(x, y, width, height, circle_x, circle_y, circle_diameter) {
        return !(x+width < circle_x+circle_diameter*0.1 ||
            x > circle_x+circle_diameter*0.9 ||
            y+height < circle_y+circle_diameter*0.1 ||
            y < circle_y+circle_diameter*0.9);
    },

    collide = function (traced, collisionObj, eventName) {
        $(observable).trigger("CollisionEvent", {tracedObject:traced, object:collisionObj, event:eventName});
    };

    return {
        registerGround : registerGround,
        registerObstacle : registerObstacle,
        removeObstacle: removeObstacle,
        registerTracingObject : registerTracingObject,
        clear : clear,
        update: update,
        on : function(event, callback){
            return $(observable).on(event, callback);
        }
    };

}(jQuery, _, DodoRunner);